#include "customscroll.h"
#include <QMouseEvent>
#include <QDebug>
#include <QApplication>
#include <QPainter>
#include <QTableWidget>
#include <QHeaderView>
#include <QScrollBar>
#include <QAbstractAnimation>


CustomScroll::CustomScroll(QTableView* table,QWidget *parent) :
    QWidget(parent)
    ,m_dragFlag(MOUSE_RELEASE)
{
    setAttribute(Qt::WA_TranslucentBackground);

    m_scrollBar = table->verticalScrollBar();
    m_scrollBar->hide();
    connect(m_scrollBar,&QScrollBar::sliderPressed,[=](){ m_scrollTimer.stop(); });           //按下滚动条
    connect(m_scrollBar,&QScrollBar::sliderMoved,[=](){ m_scrollTimer.stop(); });
    connect(m_scrollBar,&QScrollBar::sliderReleased,[=](){ m_scrollTimer.start(SCROL_SHOW_TIME); });     //松开滚动条

    animation = new QPropertyAnimation(m_scrollBar,"value",this);       //创建动画对象
    connect(animation,&QPropertyAnimation::finished,[=](){          //动画结束后启动定时器准备隐藏滚动条
        m_scrollTimer.start(SCROL_SHOW_TIME);
    });
    connect(&m_scrollTimer,SIGNAL(timeout()),this,SLOT(scrollTimeOut()));

    m_table = table;
    m_table->viewport()->installEventFilter(this);  //安装事件过滤器
    m_table->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);

    this->resize(SCROL_WIDTH,m_table->height());
    this->move(0,5);            //将滑动条移至最右侧
    this->raise();      //置顶父窗口
    m_srcollH  = m_table->height();
}

void CustomScroll::scrollTimeOut()
{
    m_scrollBar->hide();
    m_dragFlag = MOUSE_RELEASE;
}

bool CustomScroll::eventFilter(QObject *obj, QEvent *evt)
{
    static int pressPoint_y   = 0;      //记录按下位置
    static int dragPoint_y    = -1;     //拖动位置
    static qint64 pressMSec ;           //记录按下的时间点

    int scrollV_max = m_scrollBar->maximum ();
    int scrollV_min = m_scrollBar->minimum ();

    QMouseEvent *mouse =  dynamic_cast<QMouseEvent *>(evt);
    if(mouse)
    {
        //=================== 按下 ===========================
        if( mouse->type() ==QEvent::MouseButtonPress)
        {
            m_scrollTimer.stop();
            m_scrollBar->show();

            pressMSec = QDateTime::currentDateTime().toMSecsSinceEpoch();     //记录按下的时间
            dragPoint_y  = mouse->pos().y();               //当前坐标
            pressPoint_y = dragPoint_y;                      //按下的位置

            animation->stop();
            m_selectRow = m_table->indexAt(mouse->pos()).row();    //选择当前行
            m_dragFlag = MOUSE_PRESS;
        }
        //======================= 只点击了一下屏幕，未移动 =============================
        else if(mouse->type() == QEvent::MouseButtonRelease && m_dragFlag == MOUSE_PRESS)
        {
            m_dragFlag = MOUSE_RELEASE;
            m_scrollTimer.start(SCROL_SHOW_TIME);  //2S后取消滑动条显示
            m_scrollBar->show();
        }
        //==================== 鼠标移动 ==============================
        else if((m_dragFlag!= MOUSE_RELEASE) && mouse->type() == QEvent::MouseMove)
        {
            if(m_dragFlag == MOUSE_PRESS)     //鼠标按下到现在的滑动状态，即表示首次滑动
            {
                if(qAbs(dragPoint_y - mouse->pos().y()) < 5)   //判断移动阀值,避免误操作
                    return true;
                else
                {
                   m_dragFlag = MOUSE_PRESS_MOVE;           //转为移动状态
                   m_table->clearSelection();               //已经移动了,所以取消之前的选择
                   dragPoint_y = mouse->pos().y();          //获取当前坐标
                   return true;
                }
            }
            int moveValue = (dragPoint_y - mouse->pos().y()) + m_scrollBar->value(); //移动值 + 滚动条当前值 = 滑动到的位置
            dragPoint_y = mouse->pos().y();

            m_table->clearSelection();
            if(scrollV_min > moveValue) moveValue = scrollV_min;    //添加位置限制
            if(moveValue > scrollV_max) moveValue = scrollV_max;
            m_scrollBar->setValue(moveValue);   //表格显示到对应位置
        }
        //======================= 从按下滑动状态 到现在 鼠标松开，惯性滑动 =============================
        else if(m_dragFlag == MOUSE_PRESS_MOVE && mouse->type() == QEvent::MouseButtonRelease)
        {
            dragPoint_y = -1;
            int releasePoint_y = mouse->pos().y();

            int ms= QDateTime::currentDateTime().toMSecsSinceEpoch()-pressMSec;
            int Pixel_per_second=qAbs(releasePoint_y - pressPoint_y)*1000/ms;       //计算每秒像素点

            if(Pixel_per_second < 300 || qAbs(releasePoint_y - pressPoint_y) < 45)
            {
                m_dragFlag = MOUSE_RELEASE;
                return true;
            }
            else
            {
                int moveValue;
                if(ms > 1000)      //滑动的时间不能超过1s
                {
                     m_dragFlag = MOUSE_RELEASE;
                     return true;
                }
                //计算滑动得到的位置
                if(releasePoint_y - pressPoint_y > 0)     //向下滑动
                {
                    moveValue = m_scrollBar->value() - Pixel_per_second*0.2*(300/ms);   //滑动时间越长,moveValue值越小,因为不是快速滑动
                    if(moveValue < scrollV_min)
                        moveValue = scrollV_min;
                }
                else
                {
                    moveValue = m_scrollBar->value() + Pixel_per_second*0.2*(300/ms);
                    if(moveValue > scrollV_max)
                        moveValue = scrollV_max;
                }
                m_table->clearSelection();
                //滑动松开后惯性滑动动画
                animation->setDuration(2000-ms);
                animation->setEndValue(moveValue);
                animation->setEasingCurve(QEasingCurve::OutQuart);
                animation->start();
                m_dragFlag = MOUSE_RELEASE_MOVE;    //鼠标松开，惯性滑动状态
            }
        }
    }
    return QWidget::eventFilter(obj,evt);
}

